<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input type="file" id="fileInput" />
    <button id="uploadBtn">上传</button>
    <div id="progress">上传进度：0%</div>

    <script src="./spark.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dayjs@1.10.7/dayjs.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

    <script>
      // 获取 DOM 元素
      const fileInput = document.getElementById('fileInput')
      const uploadBtn = document.getElementById('uploadBtn')
      const progress = document.getElementById('progress')

      // 分片大小（1MB）
      const CHUNK_SIZE = 1024 * 1024 * 50

      // 获取 CPU 核心数
      const CPU_CORES = navigator.hardwareConcurrency || 4 // 默认 4 核
      const CONCURRENT_UPLOADS = Math.min(CPU_CORES, 4) // 限制最大并发数为 4

      let uploadedChunks = []

      // 上传文件
      uploadBtn.addEventListener('click', async () => {
        const file = fileInput.files[0]
        if (!file) {
          alert('请选择文件')
          return
        }

        // 生成文件唯一标识
        const fileHash = await calculateFileHashWithWorker(file)

        console.log(fileHash, '文件hash')

        // 查询已上传的分片
        // const uploadedChunks = await checkUploadedChunks(fileHash)

        // 边分片边上传
        await uploadFile(file, fileHash, uploadedChunks)
      })

      // 使用 Web Worker 计算文件哈希
      function calculateFileHashWithWorker(file) {
        return new Promise((resolve) => {
          const worker = new Worker('./hash-worker.js')
          worker.postMessage({ file })

          worker.onmessage = (e) => {
            resolve(e.data)
            worker.terminate() // 关闭 Worker
          }
        })
      }

      // 查询已上传的分片
      async function checkUploadedChunks(fileHash) {
        const response = await fetch('/check', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({ fileHash }),
        })
        const data = await response.json()
        return data.uploadedChunks || []
      }

      // 边分片边上传
      async function uploadFile(file, fileHash, uploadedChunks) {
        const chunkCount = Math.ceil(file.size / CHUNK_SIZE)
        let uploadedCount = uploadedChunks.length
        let currentChunkIndex = 0

        // 更新上传进度
        function updateProgress() {
          const percent = ((uploadedCount / chunkCount) * 100).toFixed(2)
          progress.textContent = `上传进度：${percent}%`
        }

        // 创建 Web Workers
        const workers = []
        for (let i = 0; i < CONCURRENT_UPLOADS; i++) {
          const worker = new Worker('./upload-worker.js')
          workers.push(worker)
        }

        // 分配任务给 Web Workers
        function assignTask(worker) {
          if (currentChunkIndex >= chunkCount) {
            return
          }

          const chunkIndex = currentChunkIndex++
          if (uploadedChunks.includes(chunkIndex)) {
            uploadedCount++
            updateProgress()
            assignTask(worker) // 继续分配下一个任务
            return
          }

          const start = chunkIndex * CHUNK_SIZE
          const chunk = file.slice(start, start + CHUNK_SIZE)

          worker.postMessage({
            chunk,
            chunkIndex,
            fileHash,
            fileName: file.name,
          })

          worker.onmessage = (e) => {
            if (e.data.success) {
              uploadedCount++
              updateProgress()
            } else {
              console.error(
                `分片 ${e.data.chunkIndex} 上传失败：`,
                e.data.error
              )
            }
            assignTask(worker) // 继续分配下一个任务
          }
        }

        // 启动所有 Workers
        workers.forEach(assignTask)

        // 等待所有分片上传完成
        while (uploadedCount < chunkCount) {
          await new Promise((resolve) => setTimeout(resolve, 100))
        }

        // 关闭所有 Workers
        workers.forEach((worker) => worker.terminate())

        // 通知服务器合并文件
        await fetch('/merge', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            fileHash,
            fileName: file.name,
            chunkCount,
          }),
        })

        alert('上传完成')
      }
    </script>
  </body>
</html>
